/*
 *  Copyright 2009-2010 APEX Data & Knowledge Management Lab, Shanghai Jiao Tong University
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

#ifndef _APEX_TENSOR_H_
#define _APEX_TENSOR_H_

/*!
 * \file apex_tensor.h
 * \brief header of all library
 * \author Tianqi Chen: tqchen@apex.sjtu.edu.cn
 */

#include "apex_tensor_config.h"
#include "apex_tensor_cpu.h"
#include "apex_tensor_func_decl.h"
#include "apex_tensor_cpu_inline.h"

// storage of sparse feature
template<typename FValue = float>
class SparseFeatureArray {
public:
	struct Entry {
		unsigned index;
		FValue value;
	};
	struct Vector {
		int num_elem;
		const Entry *ptr_elem;
		inline int size() const {
			return num_elem;
		}
		inline const Entry &operator[](int idx) const {
			return ptr_elem[idx];
		}
	};
private:
	unsigned num_row;
	std::vector<unsigned> row_ptr;
	std::vector<Entry> data;
public:
	SparseFeatureArray() {
		clear();
	}
	inline const Vector operator[](unsigned idx) const {
		Vector vec;
		if (idx < num_row) {
			vec.num_elem = row_ptr[idx + 1] - row_ptr[idx];
			vec.ptr_elem = &data[row_ptr[idx]];
		} else {
			vec.num_elem = 0;
		}
		return vec;
	}
	inline void clear() {
		data.clear();
		row_ptr.clear();
		num_row = 0;
	}
	inline void load(const char *fname) {
		this->clear();
		row_ptr.push_back(0);

		int n;
		Entry e;
		FILE *fi = fopen(fname, "r");

		while (fscanf(fi, "%d", &n) == 1) {
			row_ptr.push_back(row_ptr.back() + n);
			num_row++;
			for (int i = 0; i < n; i++) {
				assert(fscanf( fi,"%u:%f", &e.index, &e.value ) ==2 );
				data.push_back(e);
			}
		}
		fclose(fi);
	}
};

#endif
